import os, subprocess

def getCmdLine(pid):
  try:
    f = open('/proc/%d/cmdline'%(pid), 'r');
    ret = f.readline()
    f.close()
  except:
    return ''
  return ret

def getPPidAndUid(pid):
  try:
    f = open('/proc/%d/status'%(pid), 'r');
    lines = f.readlines();
    f.close()
  except Exception, e:
    return (None, None)
  ppid = 1
  uid = 0
  for line in lines:
    items = line.split()
    if items[0].startswith("PPid"):
      ppid = int(items[1])
    if items[0].startswith("Uid"):
      uid = int(items[1])
  return (ppid, uid)

class PIModCPUT:
  SIZE = 2
  STARTM = 0

  def size(self):
    return PIModCPUT.SIZE

  def start(self):
    return PIModCPUT.STARTM

  def naming(self):
    return ["utime", "stime"]

  def canUpdate(self, ot, nt):
    return True

  def update(self, pid, oldtime, nowtime, oldmet):
    try:
      f = open('/proc/%d/stat'%(pid), 'r');
      line = f.readline()
      f.close()
    except Exception, e:
      return oldmet
    items = line.split()
    oldmet[0] = int(items[13])
    oldmet[1] = int(items[14])

class PIModIO:
  SIZE = 4
  STARTM = 2

  def size(self):
    return PIModIO.SIZE

  def start(self):
    return PIModIO.STARTM

  def naming(self):
    return ["totread", "totwrite", "readbytes", "writebytes"]

  def canUpdate(self, ot, nt):
    return True

  def update(self, pid, oldtime, nowtime, oldmet):
    try:
      f = open('/proc/%d/io'%(pid), 'r');
      lines = f.readlines();
      f.close()
    except Exception, e:
      return oldmet
    rbytes = 0
    wbytes = 0
    cbytes = 0
    for line in lines:
      pair = line.split()
      if pair[0] == "read_bytes:":
        rbytes = int(pair[1])
      if pair[0] == "write_bytes:":
        wbytes = int(pair[1])
      if pair[0] == "cancelled_write_bytes:":
        cbytes = int(pair[1])
    intv = float(nowtime - oldtime)
    if (intv == 0):
      intv = 1
    oldmet[2] = float(rbytes - oldmet[0]) / intv
    oldmet[3] = float((wbytes - cbytes) - oldmet[1]) / intv
    oldmet[0] = rbytes
    oldmet[1] = wbytes - cbytes

class PIModStatus:
  SIZE = 2
  STARTM = 0

  def size(self):
    return PIModStatus.SIZE

  def start(self):
    return PIModStatus.STARTM

  def naming(self):
    return ["vmsize", "vmrss"]

  def canUpdate(self, ot, nt):
    return True

  def update(self, pid, oldtime, nowtime, oldmet):
    try:
      f = open('/proc/%d/status'%(pid), 'r');
      lines = f.readlines();
      f.close()
    except Exception, e:
      return oldmet
    for line in lines:
      items = line.split()
      if items[0].startswith("VmSize"):
        oldmet[0] = int(items[1]) * 1024
      if items[0].startswith("VmRSS"):
        oldmet[1] = int(items[1]) * 1024

class PIModPS:
  SIZE = 2
  STARTM = 0

  def __init__(self):
    self.updatet = 0
    self.pslist = {}

  def size(self):
    return PIModPS.SIZE

  def start(self):
    return PIModPS.STARTM

  def naming(self):
    return ["cpup", "memp"]

  def canUpdate(self, ot, nt):
    return True

  def runps(self, time):
    if self.updatet == time:
      return
    self.updatet = time
    pp = subprocess.Popen(['ps','aux'], bufsize=1024, \
                     stdout=subprocess.PIPE)
    topOut = pp.stdout
    lines = topOut.readlines()
    topOut.close();
    for line in lines:
      items = line.split()
      if items[1].isdigit():
        cpup = float(items[2])
        memp = float(items[3])
        pid = int(items[1])
        if pid in self.pslist:
          self.pslist[pid][0] = cpup
          self.pslist[pid][1] = memp
        else:
          self.pslist[pid] = [cpup, memp]

  def update(self, pid, oldtime, nowtime, oldmet):
    self.runps(nowtime)
    if pid in self.pslist:
      oldmet[0] = self.pslist[pid][0]
      oldmet[1] = self.pslist[pid][1]

class PIModTest:
  def __init__(self):
    pp = subprocess.Popen(['ps','aux'], bufsize=1024, \
                     stdout=subprocess.PIPE)
    topOut = pp.stdout
    lines = topOut.readlines()
    topOut.close();
#    lineno = 100
#    print lines[lineno]
#    self.pid = int(lines[lineno].split()[1])
    self.pid = 9825

  def test(self, mod):
    print mod.naming()
    oldtime = 100
    nowtime = 200
    oldmet = [0] * mod.size()
    mod.update(self.pid, oldtime, nowtime, oldmet)
    print oldmet

if __name__ == '__main__':
  mod1 = PIModCPUT()
  mod3 = PIModIO()
  mod2 = PIModStatus()
  test = PIModTest()
  test.test(mod1)
  test.test(mod2)
  test.test(mod3) 
